#pragma once
/* 
* COPYRIGHT 2012 Mafahir Fairoze
* 
* This file is part of Vector Template Library (Vtl) v1.0.
* (Project Website : http://mafahir.wordpress.com/projects/neuralplusplus)
* 
* Vector Template Library (Vtl) v1.0 is a free software. You can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
* 
* Vector Template Library (Vtl) v1.0 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License <http://www.gnu.org/licenses/> for more details.
*/

#include "Vtl/eigen.h"
#include <Eigen/StdVector>
#include "Vtl/AABBox.h"

namespace Vtl
{
	template <typename Scalar, int Dimension>
	class MeshBuffer
	{
	public:
		typedef Eigen::Matrix<Scalar, Dimension, 1> VectorType;
		typedef AABBox<Scalar, Dimension> BoundingBox;
		typedef std::vector<VectorType, Eigen::aligned_allocator<VectorType> > VertexBuffer;
		typedef std::vector<int> IndexBuffer;

		/*!
		*  \brief Returns the array of vertices.
		*  \return const VertexBuffer & 
		*/
		const VertexBuffer & getVertices() const { return vertices; }

		/*!
		*  \brief Returns the array of vertices.
		*  \return VertexBuffer & 
		*/
		VertexBuffer & getVertices() { return vertices; }

		/*!
		*  \brief Returns the array of indices.
		*  \return const IndexBuffer & 
		*/
		const IndexBuffer & getIndices() const { return indices; }

		/*!
		*  \brief Returns the array of indices.
		*  \return IndexBuffer & 
		*/
		IndexBuffer & getIndices() { return indices; }

		/*!
		*  \brief Returns the vertex array length.
		*  \return int 
		*/
		int getVertexCount() const { return vertices.size(); }

		/*!
		*  \brief Returns the index array length.
		*  \return int 
		*/
		int getIndexCount() const { return indices.size(); }

		/*!
		*  \brief Returns the bounding box.
		*  \note Bounding box needs to be recalculated if vertices changes.
		*  \return const BoundingBox & 
		*/
		const BoundingBox & getBoundingBox() const { return aabbox; }

		/*!
		*  \brief Recalculates the bounding box.
		*/
		void RecalculateBoundingBox()
		{
			if (vertices.empty())
				aabbox.Reset();
			else
			{				
				for (int i=0; i<vertices.size(); ++i)
					aabbox.AddInPoint(vertices[i]);
			}
		}

		/*!
		*  \brief Appends a list of vertices and indices to the existing mesh.
		*  \param[in] _Vertices the array of vertices.
		*  \param[in] _NumVertices the number of vertices in the array.
		*  \param[in] _Indices the array of indices.
		*  \param[in] _NumIndices the number of indices in the array.
		*/
		void Append(const VectorType * const _Vertices, const int &_NumVertices, const int *_Indices, const int &_NumIndices)
		{
			const int vertex_count = vertices.size();
			int i;
			if(vertex_count == _NumVertices)
			{
				bool is_equal = true;
				for(i=0; i<_NumVertices; ++i)
				{
					if(vertices[i] != _Vertices[i])
					{
						is_equal = false;
						break;
					}
				}
				if(is_equal)
					return;				
			}
			for (i=0; i<_NumVertices; ++i)
			{
				vertices.push_back(_Vertices[i]);
				aabbox.AddInPoint(_Vertices[i]);
			}

			for (i=0; i<_NumIndices; ++i)
			{
				indices.push_back(_Indices[i] + vertex_count);
			}
		}

	protected:
		VertexBuffer vertices;
		IndexBuffer indices;
		BoundingBox aabbox;
	};

	typedef MeshBuffer<double, 3> MeshBuffer3d;
	typedef MeshBuffer<double, 2> MeshBuffer2d;
	typedef MeshBuffer<float, 3> MeshBuffer3f;
	typedef MeshBuffer<float, 2> MeshBuffer2f;
	typedef MeshBuffer<int, 3> MeshBuffer3i;
	typedef MeshBuffer<int, 2> MeshBuffer2i;
};